import sys
import time
import os
import requests
import hashlib
import json
import warnings
import requests
warnings.filterwarnings("ignore")



class DomainApiUtils:
    def __init__(self, api_url: str, user_name: str = None, api_password: str = None):
        """ 初始化类，用户认证和域名apidomainkey必选其一

        :param api_url  :       接口地址
        :param user_name:       在西部数码的账号
        :param api_password:    SSL的专用api 密码，在网站https://www.west.cn/manager/API/APIconfig.asp 中设置
        """
        self.api_url = api_url  # api 地址
        self.user_name = user_name  # 账号
        self.api_password = api_password  # api 密码

    def get_public_parm(self, apidomainkey: str = None) -> dict:
        """    获取公共参数
        :param  apidomainkey    域名ApiKey 32位apikey，为域名管理密码的md5值，可在域名控制面板中直接复制
        """
        if apidomainkey:
            return {
                "apidomainkey" : apidomainkey
            }
        if self.user_name or self.api_password is None:
            print("API 认证参数错误,apidomainkey 认证或账号认证选择一种。程序退出")
            sys.exit(0)
        __apikey = self.get_convert_md5(self.api_password)
        __public_parm = {
            "username": self.user_name,
            "apikey": __apikey,
        }
        return __public_parm

    def get_convert_md5(self, __string: str, upper: bool = False) -> str:
        """ 计算字符串md5值

        :param __string:    输入字符串
        :param upper:       是否转大写
        :return:            字符串md5
        """
        __my_hash = hashlib.md5()
        __my_hash.update(__string.encode('GBK'))
        __hash = __my_hash.hexdigest()
        if upper:
            return str(__hash).upper()
        else:
            return str(__hash).lower()

    def encode_parm(self, __rep_parm: dict, charset: str = 'GBK') -> dict:
        """ 统一转换参数编码

        :param __rep_parm:  要转换的字典
        :param charset:     字符集
        :return:            转换后的新字典
        """
        __encoded_data = {}
        for k, v in __rep_parm.items():
            if v and isinstance(v, str):
                __encoded_data[k] = v.encode(charset, errors='ignore').decode(charset)
            else:
                __encoded_data[k] = v
        return __encoded_data

    def do_api(self, __act_url: str, rep_parm: dict = {}, apidomainkey: str = None, isget=True):
        '''    调用接口
        :param    __act_url     请求 apiurl
        :param    rep_parm      请求参数
        :param    apidomainkey: api 认证key
        :param    isget         非get方法则为post
        :return   返回元祖，状态和请求返回结果
        '''
        #    合并公共参数
        if __act_url is not None:
            __api_url = self.api_url + __act_url
        else:
            __api_url = self.api_url
        __rep_status, __respon = self.request_act(__api_url, rep_parm, apidomainkey=apidomainkey, isget=isget)
        return __rep_status, __respon

    def request_act(self, __url: str, __rep_parm: dict, apidomainkey: str = None, isget: bool = True, timeout: int = 10, charset: str = 'GBK'):
        '''    post 请求

        :param    __url        : 请求url
        :param    __rep_parm   : 请求参数
        :param    apidomainkey : api 认证key
        :param    isget        : 非get方法则为post
        :param    timeout      : 超时时间
        :param    charset      : 字符集
        :return   返回元祖，状态和请求返回结果
        '''
        try:
            session = requests.Session()
            session.keep_alive = False                                              #   关闭 多余链接
            if isget:
                __rep_parm.update(self.get_public_parm(apidomainkey=apidomainkey))  #   合并公共参数
                __rep_parm = self.encode_parm(__rep_parm, charset)                  #   转换编码
                __respon = session.get(__url, params=__rep_parm, timeout=timeout)
            else:
                __headers = {
                    'Content-Type': f'application/x-www-form-urlencoded;charset={charset}',
                }
                __rep_parm = self.encode_parm(__rep_parm, charset)
                __respon = session.post(__url, data=__rep_parm, params=self.get_public_parm(apidomainkey=apidomainkey), headers=__headers, timeout=timeout)
            return True, __respon
        except requests.exceptions.Timeout:
            return False, {'code': 500, 'msg': f'Request connection timeout......', 'data': None}
        except requests.exceptions.ConnectionError as e:
            return False, {'code': 500, 'msg': f'Request connection error:{repr(e)}', 'data': None}
        except Exception as e:
            return False, {'code': 500, 'msg': f'Request error:{repr(e)}', 'data': None}


class WestDomainUtils(DomainApiUtils):
    def __init__(self, api_url: str, user_name: str = None, api_password: str = None):
        """ 初始化类，用户认证和域名apidomainkey必选其一

        :param api_url  :       接口地址
        :param user_name:       您在我司的用户名
        :param api_password:    认证密码
        """
        #    api 地址
        self.api_url = api_url
        #    账号
        self.user_name = user_name
        #    api 密码
        self.api_password = api_password
        super(DomainApiUtils, self).__init__()

    def domain_dnsrec_list(self,__domain: str, hostname: str = None, record_type: str = None, record_value:str = None ,record_line: str = None, limit:int = 20, pageno:int = 1, apidomainkey: str = None):
        """ 获取域名解析

        :param __domain  :       查询域名，如www.test.com或test.com
        :param hostname:         指定主机头/完整域名
        :param record_type:      指定解析类型 限 A,CNAME,MX,TXT,AAAA,SRV
        :param record_line:      线路: (默认="" ,电信="LTEL" ,联通="LCNC" ,移动="LMOB" ,教育网="LEDU" , 'LSEO':'搜索引擎', 'LFOR': '境外')
        :param record_value:     解析值
        :param limit:            每页大小默认20
        :param pageno:           第几页
        :param apidomainkey:     域名api认证key
        """
        print("############### 获取域名解析记录    #####################")
        __rep_parm = {
            "act": 'dnsrec.list',
            "domain": __domain,
            "hostname": hostname,
            "record_type": record_type,
            "record_line": record_line,
            "record_value":record_value,
            "limit":limit,
            "pageno":pageno
        }
        __rep_status, __respon = self.do_api(None, rep_parm=__rep_parm, apidomainkey=apidomainkey, isget=False)
        __items =  None
        if __rep_status:
            __json_data = __respon.json()           # 获取返回json数据
            #print(json.dumps(__json_data, indent=4, sort_keys=True).encode('GBK').decode('unicode_escape'))
            if __json_data.get('code', 500) == 200:
                __body = __json_data.get('body',dict)
                if __body:
                    __items = __body.get('items',list)
                    for __item in __items:
                        __hostname = __item.get('hostname',None)
                        __record_type = __item.get('record_type',None)
                        __record_value = __item.get('record_value',None)
                        __record_line = __item.get('record_line',None)
                        print(f'hostname:{__hostname}\nrecord_type:{__record_type}\nrecord_value:{__record_value}\nrecord_line:{__record_line}\n',end='\n')
                    if not __items:
                        print('返回数据为空')
                else:
                    print('返回数据为空')
            else:
                print('返回状态失败', __json_data.get('msg', None))
        else:
            print(__respon)
        return __items

    def domain_dnsrec_add(self,__domain: str, __record_type: str, __hostname: str, __record_value: str, record_line: str = None, record_ttl: int = 900, record_level: int = None, apidomainkey: str = None):
        """ 域名添加解析

        :param __domain  :       操作域名。如www.test.com或test.com
        :param __record_type:    解析类型 限 A,CNAME,MX,TXT,AAAA,SRV
        :param __hostname:       指定子域名主机名或完整子域名， 如www.test.com或www
        :param __record_value:   解析值
        :param record_line:      线路: (默认="" ,电信="LTEL" ,联通="LCNC" ,移动="LMOB" ,教育网="LEDU" , 'LSEO':'搜索引擎', 'LFOR': '境外')
        :param record_ttl:       解析生效时间值 60~86400 单位秒 (默认900)
        :param record_level:     优先级别 1-100 默认(10) 仅mx记录有效
        :param apidomainkey:     域名api认证key
        """
        print("############### 添加域名解析    #####################")
        __rep_parm = {
            "act": "dnsrec.add",
            "domain": __domain,
            "record_type": __record_type,
            "hostname": __hostname,
            "record_value": __record_value,
            "record_line": record_line,
            "record_ttl": record_ttl,
            "record_level": record_level,
        }
        __rep_status, __respon = self.do_api(None, rep_parm = __rep_parm, apidomainkey=apidomainkey, isget = False)
        if __rep_status:
            __json_data = __respon.json()           # 获取返回json数据
            #print(json.dumps(__json_data, indent=4, sort_keys=True).encode('GBK').decode('unicode_escape'))
            if __json_data.get('code', 500) == 200:
                __body = __json_data.get('body')
                if __body:
                    return True, __body.get('record_id',None)
                else:
                    return False, "解析添加成功,body返回未null"
            else:
                return False, f"解析添加失败,{__json_data.get('msg', None)}"
        else:
            return False, __respon

    def domain_dnsrec_modify(self,__domain: str, __record_type: str, __hostname: str, __record_value: str, record_id: int = None, record_line: str = None, apidomainkey: str = None):
        """ 域名修改解析

        :param __domain  :       操作域名。如www.test.com或test.com
        :param __record_type:    解析类型 限 A,CNAME,MX,TXT,AAAA,SRV
        :param __hostname:       指定子域名主机名或完整子域名， 如www.test.com或www
        :param __record_value:   解析值
        :param record_id:        指定记录ID(为空或0)
        :param record_line:      线路: (默认="" ,电信="LTEL" ,联通="LCNC" ,移动="LMOB" ,教育网="LEDU" , 'LSEO':'搜索引擎', 'LFOR': '境外')
        :param apidomainkey:     域名api认证key
        """
        print("############### 修改域名解析记录值    #####################")
        __rep_parm = {
            "act": "dnsrec.modify",
            "record_id": record_id,
            "domain": __domain,
            "hostname": __hostname,
            "record_value": __record_value,
            "record_type": __record_type,
            "record_line": record_line,
        }
        __rep_status, __respon = self.do_api(None, rep_parm=__rep_parm, apidomainkey=apidomainkey, isget=False)
        if __rep_status:
            __json_data = __respon.json()           # 获取返回json数据
            #print(json.dumps(__json_data, indent=4, sort_keys=True).encode('GBK').decode('unicode_escape'))
            if __json_data.get('code', 500) == 200:
                __body = __json_data.get('body')
                if __body:
                    return True, __body
                else:
                    return False, "解析修改成功,body返回为null"
            else:
                return False, f"解析修改失败,{__json_data.get('msg', None)}"
        else:
            return False, __respon

    def domain_dnsrec_remove(self,__domain: str, record_id: int = None, record_type: str = None, hostname: str = None, record_line: str = None, apidomainkey: str = None):
        """ 域名删除解析，record_id优先，如没有提供record_id ，hostname和record_type必填写。如果需要指定解析值删除请指定记录ID(record_id优先)

        :param __domain  :       操作域名。如www.test.com或test.com
        :param record_id:        指定记录ID(为空或0)，优先
        :param record_type:      解析类型 限 A,CNAME,MX,TXT,AAAA,SRV
        :param hostname:         指定子域名主机名或完整子域名， 如www.test.com或www
        :param record_line:      线路: (默认="" ,电信="LTEL" ,联通="LCNC" ,移动="LMOB" ,教育网="LEDU" , 'LSEO':'搜索引擎', 'LFOR': '境外')
        :param apidomainkey:     域名api认证key
        """
        print("############### 删除域名解析    #####################")
        if record_id and hostname and record_type is None:
            return False, F"record_id 或者 hostname和record_type 不能为空"
        __rep_parm = {
            "act": "dnsrec.remove",
            "record_id": record_id,
            "domain": __domain,
            "hostname": hostname,
            "record_type": record_type,
            "record_line": record_line,
        }
        __rep_status, __respon = self.do_api(None, rep_parm=__rep_parm, apidomainkey=apidomainkey, isget=False)
        if __rep_status:
            __json_data = __respon.json()           # 获取返回json数据
            #print(json.dumps(__json_data, indent=4, sort_keys=True).encode('GBK').decode('unicode_escape'))
            if __json_data.get('code', 500) == 200:
                __body = __json_data.get('body')
                if __body:
                    return True, __body
                else:
                    return False, "解析删除成功,body返回未null"
            else:
                return False, f"解析删除失败,{__json_data.get('msg', None)}"
        else:
            return False, __respon




try:
    response = requests.get('https://ipv6.icanhazip.com', timeout=10)
    if response.status_code == 200:
        ipv6_address = response.text.strip()
        print(f"本机公网 IPv6 地址是: {ipv6_address}")
    else:
        print(f"请求失败，状态码: {response.status_code}")
except requests.RequestException as e:
    print(f"请求发生错误: {e}")





api_url = r'https://api.west.cn/API/v2/domain/dns/'  # 接口地址
user_name    = 'zhaichengfu'      # 账号
api_password = '2hpwgagf'      # api 密码
yuMing = 'yeshijixie.com'

__util = WestDomainUtils(api_url, user_name, api_password)

# ecord_line:      线路: (默认="" ,电信="LTEL" ,联通="LCNC" ,移动="LMOB" ,
# 教育网="LEDU" , 'LSEO':'搜索引擎', 'LFOR': '境外')

############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","www",ipv6_address,record_line='', apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","www",ipv6_address,record_line='', apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","@",ipv6_address,record_line='LTEL', apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","www",ipv6_address,record_line='LTEL',apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","@",ipv6_address,record_line='LCNC', apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","www",ipv6_address,record_line='LCNC',apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","@",ipv6_address,record_line='LMOB', apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)
############### 修改域名解析    #####################
__status,__body = __util.domain_dnsrec_modify(yuMing,"AAAA","www",ipv6_address,record_line='LMOB',apidomainkey='bab32ec0c4c880cd692b749a2dfef986')
print(__status, __body)




